<HTML><title>Function Objects</title>
<BODY>
<h2><a name="Aggregation"></a>Example 2: Aggregation</h2>
<p><i>Aggregation</i> is a generalized form of summation or integration. Aggregation 
  functions visit all cells of a matrix and derive a single number as &quot;summary 
  information&quot;. Number of elements, mean, maximum, minimum, variance, root-mean-square 
  are classic aggregation functions, but there are many more. Floods of data are 
  too difficult to understand - a single number sells better to management. More 
  seriously, the scientific process takes observations and tries to find patterns, 
  the essentials of knowledge, which are more compact and easier to internalize 
  than the observations itself. The most compact representation of knowledge is, 
  of course, a single number. 
<p>We will use the prefabricated <tt>plus</tt> and <tt>square</tt> function objects 
  to compute the sum of squares of a 1-d matrix, but first, let's get prepared. 
<pre>double[] v1 = {0, 1, 2, 3}; <br>DoubleMatrix1D matrix = new DenseDoubleMatrix1D(v1);

// the naming shortcut (alias) saves some keystrokes:
cern.jet.math.Functions F = cern.jet.math.Functions.functions;
</pre>
<hr>
<h2>Aggregation over one matrix </h2>
<pre>
// Sum( x[i]*x[i] ) 
System.out.println(matrix.aggregate(F.plus,F.square));
// --> 14

// Sum( x[i]*x[i]*x[i] ) 
System.out.println(matrix.aggregate(F.plus,F.pow(3)));
// --> 36

// Sum( x[i] ) 
System.out.println(matrix.aggregate(F.plus,F.identity));
// or the specialized version
System.out.println(matrix.zSum());
// --> 6
</pre>
<pre>// Min( x[i] ) 
System.out.println(matrix.aggregate(F.min,F.identity));
// --> 0

// Max( Sqrt(x[i]) / 2 ) 
System.out.println(matrix.aggregate(F.max,F.chain(F.div(2),F.sqrt)));
// --> 0.8660254037844386

// Number of all cells with 0 <= value <= 2
System.out.println(matrix.aggregate(F.plus,F.between(0,2)));
// --> 3

// Number of all cells with 0.8 <= Log2(value) <= 1.2
System.out.println(matrix.aggregate(F.plus,F.chain(F.between(0.8,1.2),F.log2)));
// --> 1

// Product( x[i] )
System.out.println(matrix.aggregate(F.mult,F.identity));
// --> 0

// Product( x[i] ) of all x[i] > limit
final double limit = 1;
DoubleFunction f = new DoubleFunction() {
	public final double apply(double a) { return a>limit ? a : 1; }
};
System.out.println(matrix.aggregate(F.mult,f));
// --> 6

// RMS (Root-Mean-Square) is a measure of the average "size" of the elements of a data sequence.
double rms = Math.sqrt(matrix.aggregate(F.plus,F.square) / matrix.size());</pre>
<hr>
<h2>Aggregation over two matrices </h2>
<pre>
DoubleMatrix1D x = matrix.copy();
DoubleMatrix1D y = matrix.copy();
// x is 0 1 2 3 
// y is 0 1 2 3 

// Sum( x[i]*y[i] )
System.out.println(x.aggregate(y, F.plus, F.mult));
// --> 14

// Sum( (x[i]+y[i])^2 )
System.out.println(x.aggregate(y, F.plus, F.chain(F.square,F.plus)));
// --> 56


// Sum(Math.PI * Math.log(y[i] / x[i]))<br>x.aggregate(y, F.plus, F.chain(F.mult(Math.PI),F.chain(F.log,F.swapArgs(F.div))));

// equivalent, but perhaps less error prone and more readable: 
x.aggregate(y, F.plus,
   new DoubleDoubleFunction() {
      public double apply(double a, double b) { return Math.PI*Math.log(b/a); }
   }
);
</pre>
<p>Try the examples on 2-d or 3-d matrices. They work without changes (except, 
  of course, that construction of the source matrix need to be modified). </p>
</BODY>
</HTML>